// 1.C++继承

/**
 * 1. 什么是继承？ 
 *      面向对象里的一个重要概念。继承允许我们用一个类来定义另一的类，这使得创建和维护另一个应用程序更容易。达到代码的重用功能和提高执行效率。
 * 2. 基类和派生类
 * 3. 继承语法:
 *      class derived-class : access-specifier base-class;
 * 4. 访问控制:
 *      public    类内可以访问，类外可以访问，派生类可以访问
 *      protected 类内可以访问，类外不可访问，派生类可以访问
 *      private   类内可以访问，类外不可访问，派生类不可访问
 * 5. 什么继承？什么不继承？
 *      派生类继承基类所有方法，以下除外：
 *      基类的构造函数、析构函数、拷贝构造函数不继承。
 *      基类的重载运算符
 *      基类的友元函数
 * 6. 继承类型
 *      public继承，基类的公有成员，还是公有成员；基类的受保护成员，还是受保护成员；基类的私有成员，还是私有成员
 *      protected继承，基类的公有成员，变成受保护成员；基类的受保护成员，还是受保护成员；基类的私有成员，还是私有成员
 *      private几个，基类的公有成员，变为私有成员；基类的受保护成员，变为私有成员；基类的私有成员，还是私有成员
 * 7. 多继承
 *      语法：class derived-class : access-specifier base-class1,access-specifier base-class2 ...;
 * 
 * 
 * 扩展(#xx1 末尾补1):
 * 1. #111、#121 砖石继承问题 
*/

#include <iostream>
#define __mark 121

/**
 * #111 砖石继承问题1
*/
#if 111 == __mark
class A
{
public:
  A(int _a) : a(_a) {}
  void func()
  {
    std::cout << "func()..." << std::endl;
  }

private:
  int a;
};

class B : public A
{
public:
  B(int _a, int _b) : A(_a), b(_b) {}

private:
  int b;
};

class C : public A
{
public:
  C(int _a, int _c) : A(_a), c(_c) {}

private:
  int c;
};

class D : public B, public C
{
public:
  D(int _a, int _b, int _c, int _d) : B(_a, _b), C(_a, _c), d(_d) {}

private:
  int d;
};
int main(void)
{
  D d(1, 2, 3, 4);
  // d.A::func(); // .A有二义性，不知道是哪个子对象
  // A *pa = (A *)&d;// 转化出现二义性，d中含有两个基类对象A，隐式类型转换不知道让pa指向那个子对象
  // d.func();// func有二义性，系统不知道是调用B类还是C类的func()

  A *pa1 = (A *)(B *)&d;
  A *pa2 = (A *)(C *)&d;
  pa1->func();
  pa2->func();
  d.B::func();
  d.C::func();

  printf("-------------end-------------\n");
  return 0;
}
/**
 * #121 砖石继承问题2————引用虚继承来解决
*/
#elif (121 == __mark)
class A
{
private:
  int a;

public:
  A(int _a) : a(_a) {}
  void func()
  {
    std::cout << "func()..." << std::endl;
  }
};

class B : virtual public A
{
private:
  int b;

public:
  B(int _a, int _b) : A(_a), b(_b){};
};

class C : virtual public A
{
private:
  int c;

public:
  C(int _a, int _c) : A(_a), c(_c) {}
};

class D : public B, public C
{
private:
  int d;

public:
  // 这边写法不同，要显式设置虚基子对象
  D(int _a, int _b, int _c, int _d) : A(_a), B(_a, _b), C(_a, _c), d(_d) {}
};
int main(void)
{
  D d(1, 2, 3, 4);
  A *pa = (A *)&d;
  pa->func();
  d.func();
  printf("-------------end-------------\n");
  return 0;
}
#endif